<?php
/**
 ***********************************************************************************************************************
 * 访问规则
 * @author llq
 ***********************************************************************************************************************
 */
namespace soa\access\model\db;
use artisan\config;

/**
 * Class rule
 * @package soa\access\model\db
 */
class rule
{
    /**
     * 黑白名单数据表
     */
    const BLACKWHITE_TBL = 'tbl_black_white';

    /**
     * 自定义规则数据表
     */
    const RULE_TBL = 'tbl_custom_rule';

    /**
     *******************************************************************************************************************
     * 黑白名单处理
     *******************************************************************************************************************
     */

    /**
     * 添加黑名单
     * @param $ip
     * @return bool|int
     */
    public function addBlack($ip, $note = '')
    {
        if(empty($ip) || !is_string($ip) || !preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $ip)) {
            return false;
        }

        $del = $this->delBlack($ip);
        if(!empty($del)) {
            return $this->getDb()->table(self::BLACKWHITE_TBL)->insert(
                [
                    'ip' => $ip,
                    'is_segment' => '0',
                    'is_black' => '1',
                    'note' => (string)$note
                ]
            );
        }
        return false;
    }

    /**
     * 添加黑名单段
     * @param $ip_segment
     * @return bool|int
     */
    public function addBlackSegment($ip_segment, $note = '')
    {
        if(
            empty($ip_segment) ||
            !is_string($ip_segment) ||
            !preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $ip_segment)
        ) {
            return false;
        }

        //$del = $this->delBlackSegment($ip_segment);
        $del = $this->getDb()->table(self::BLACKWHITE_TBL)->delete(
            [
                'ip like' => $ip_segment . '%'
            ]
        );
        //($del);
        if(!empty($del)) {
            return $this->getDb()->table(self::BLACKWHITE_TBL)->insert(
                [
                    'ip' => $ip_segment,
                    'is_segment' => '1',
                    'is_black' => '1',
                    'note' => (string)$note
                ]
            );
        }
        return false;
    }

    /**
     * 添加白名单
     * @param $ip
     * @return bool|int
     */
    public function addWhite($ip, $note = '')
    {
        if(empty($ip) || !is_string($ip) || !preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $ip)) {
            return false;
        }

        $del = $this->delWhite($ip);
        if(!empty($del)) {
            return $this->getDb()->table(self::BLACKWHITE_TBL)->insert(
                [
                    'ip' => $ip,
                    'is_segment' => '0',
                    'is_black' => '0',
                    'note' => (string)$note
                ]
            );
        }
        return false;
    }

    /**
     * 添加白名单段
     * @param $ip_segment
     * @return bool|int
     */
    public function addWhiteSegment($ip_segment, $note = '')
    {
        if(
            empty($ip_segment) ||
            !is_string($ip_segment) ||
            !preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $ip_segment)
        ) {
            return false;
        }

        //$del = $this->delWhiteSegment($ip_segment);
        $del = $this->getDb()->table(self::BLACKWHITE_TBL)->delete(
            [
                'ip like' => $ip_segment . '%'
            ]
        );
        //myprint($del,true);
        if(!empty($del)) {
            return $this->getDb()->table(self::BLACKWHITE_TBL)->insert(
                [
                    'ip' => $ip_segment,
                    'is_segment' => '1',
                    'is_black' => '0',
                    'note' => (string)$note
                ]
            );
        }
        return false;
    }

    /**
     * 删除黑名单
     * @return bool|int|string
     */
    public function delBlack($ip)
    {
        if(empty($ip) || !is_string($ip) || !preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $ip)) {
            return false;
        }

        return $this->getDb()->table(self::BLACKWHITE_TBL)->delete(
            [
                'ip' => $ip,
                'is_segment' => '0',
            ]
        );
    }

    /**
     * 删除黑名单段
     * @return bool|int|string
     */
    public function delBlackSegment($ip_segment)
    {
        if(empty($ip_segment) || !is_string($ip_segment) || !preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $ip_segment)) {
            return false;
        }

        return $this->getDb()->table(self::BLACKWHITE_TBL)->delete(
            [
                'ip' => $ip_segment,
                'is_segment' => '1',
            ]
        );
    }

    /**
     * 删除白名单
     * @return bool|int|string
     */
    public function delWhite($ip)
    {
        if(empty($ip) || !is_string($ip) || !preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $ip)) {
            return false;
        }

        return $this->getDb()->table(self::BLACKWHITE_TBL)->delete(
            [
                'ip' => $ip,
                'is_segment' => '0',
            ]
        );
    }

    /**
     * 删除白名单段
     * @return bool|int|string
     */
    public function delWhiteSegment($ip_segment)
    {
        if(empty($ip_segment) || !is_string($ip_segment) || !preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $ip_segment)) {
            return false;
        }

        return $this->getDb()->table(self::BLACKWHITE_TBL)->delete(
            [
                'ip' => $ip_segment,
                'is_segment' => '1',
            ]
        );
    }


    /**
     * 获取黑名单原始数据
     * @param $ip_segment
     * @return array
     */
    public function getBlacks(array $where = [], array $limit = [])
    {
        return $this->getDb()->table(self::BLACKWHITE_TBL)->getAll(
            array_merge(
                $where,
                [
                    'is_black' => '1'
                ]
            ),
            $limit,
            'id desc'
        ) ?: [];
    }

    /**
     * @param array $where
     * @return int
     */
    public function getBlackCounts(array $where = [])
    {
        return $this->getDb()->table(self::BLACKWHITE_TBL)->count(
            array_merge(
                $where,
                [
                    'is_black' => '1'
                ]
            )
        ) ?: 0;
    }

    /**
     * 获取白名单原始数据
     * @param $ip_segment
     * @return array
     */
    public function getWhites(array $where = [], array $limit = [])
    {
        return $this->getDb()->table(self::BLACKWHITE_TBL)->getAll(
            array_merge(
                $where,
                [
                    'is_black' => '0'
                ]
            ),
            $limit,
            'id desc'
        ) ?: [];
    }

    /**
     * @param array $where
     * @return int
     */
    public function getWhiteCounts(array $where = [])
    {
        return $this->getDb()->table(self::BLACKWHITE_TBL)->count(
            array_merge(
                $where,
                [
                    'is_black' => '0'
                ]
            )
        ) ?: 0;
    }

    /**
     *******************************************************************************************************************
     * 访问规则处理
     *******************************************************************************************************************
     */

    /**
     * 添加自定义IP访问规则
     * @param $service
     * @param $ip
     * @param $rule_index
     * @param int $cnt
     * @return bool|int
     */
    public function addIpRule($service, $ip, $rule_index, $cnt = 0, $note = '')
    {
        if(
            empty($service) ||
            !is_string($service) ||
            empty($ip) ||
            !is_string($ip) ||
            !preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $ip) ||
            empty($rule_index) ||
            !is_string($rule_index) ||
            !is_numeric($cnt)
        ) {
            return false;
        }
        $del = $this->delRuleByIp($service, $ip, $rule_index);
        if(!empty($del)) {
            return $this->getDb()->table(self::RULE_TBL)->insert(
                [
                    'name' => $ip,
                    'service' => $service,
                    'rule_index' => $rule_index,
                    'is_account' => '0',
                    'cnt' => $cnt,
                    'note' => $note
                ]
            );
        }
        return false;
    }

    /**
     * 添加自定义账号访问规则
     * @param $service
     * @param $account
     * @param $rule_index
     * @param int $cnt
     * @return bool|int
     */
    public function addAccountRule($service, $account, $rule_index, $cnt = 0, $note = '')
    {
        if(
            empty($service) ||
            !is_string($service) ||
            empty($account) ||
            !is_string($account) ||
            empty($rule_index) ||
            !is_string($rule_index) ||
            !is_numeric($cnt)
        ) {
            return false;
        }
        $del = $this->delRuleByAccount($service, $account, $rule_index);
        //myprint($del, true);
        if(!empty($del)) {
            return $this->getDb()->table(self::RULE_TBL)->insert(
                [
                    'name' => $account,
                    'service' => $service,
                    'rule_index' => $rule_index,
                    'is_account' => '1',
                    'cnt' => $cnt,
                    'note' => (string)$note
                ]
            );
            //myprint($this->getDb()->getLastQuery());
        }
        return false;
    }


    /**
     * 根据IP删除访问规则
     * @param $service
     * @param $ip
     * @param string $rule_index
     * @return bool
     */
    public function delRuleByIp($service, $ip, $rule_index)
    {
        if(
            empty($service) ||
            !is_string($service) ||
            empty($ip) ||
            !is_string($ip) ||
            !preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $ip) ||
            empty($rule_index) ||
            !is_string($rule_index)
        ) {
            return false;
        }
        return $this->getDb()->table(self::RULE_TBL)->delete(
            [
                'name' => $ip,
                'service' => $service,
                'rule_index' => $rule_index,
                'is_account' => '0'
            ]
        );
    }

    /**
     * 根据账号删除访问规则
     * @param $service
     * @param $account
     * @param string $rule_index
     * @return bool
     */
    public function delRuleByAccount($service, $account, $rule_index)
    {
        if(
            empty($service) ||
            !is_string($service) ||
            empty($account) ||
            !is_string($account) ||
            empty($rule_index) ||
            !is_string($rule_index)
        ) {
            return false;
        }
        return $this->getDb()->table(self::RULE_TBL)->delete(
            [
                'name' => $account,
                'service' => $service,
                'rule_index' => $rule_index,
                'is_account' => '1'
            ]
        );
    }

    /**
     * @param array $where
     * @param array $limit
     * @return array
     */
    public function getIpRules(array $where = [], array $limit = [])
    {
        return $this->getDb()->table(self::RULE_TBL)->getAll(
            array_merge($where, ['is_account' => '0']),
            $limit,
            'id desc'
        ) ?: [];
    }

    /**
     * @param array $where
     * @return int
     */
    public function getIpRuleCounts(array $where = [])
    {
        return $this->getDb()->table(self::RULE_TBL)->count(
            array_merge($where, ['is_account' => '0'])
        ) ?: 0;
    }


    /**
     * @param array $where
     * @param array $limit
     * @return array
     */
    public function getAccountRules(array $where = [], array $limit = [])
    {
        return $this->getDb()->table(self::RULE_TBL)->getAll(
            array_merge($where, ['is_account' => '1']),
            $limit,
            'id desc'
        ) ?: [];
    }

    /**
     * @param array $where
     * @return int
     */
    public function getAccountRuleCounts(array $where = [])
    {
        return $this->getDb()->table(self::RULE_TBL)->count(
            array_merge($where, ['is_account' => '1'])
        ) ?: 0;
    }


    /**
     * db服务
     * @var \artisan\db
     */
    private $db;
    /**
     * 获取db服务
     * @return \artisan\db
     */
    private function getDb()
    {
        if(empty($this->db)) {
            $this->db = \artisan\db::connect(config::get('access', 'db'));
        }
        return $this->db;
    }

}